package avicit.bdp.dms.oauth2.validator;

import avicit.bdp.dms.oauth2.token.OauthTokenService;
import avicit.bdp.dms.tdm.dto.AppClientDTO;
import avicit.platform6.core.spring.SpringFactory;
import org.apache.commons.lang3.StringUtils;
import org.apache.oltu.oauth2.as.request.OAuthRequest;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Set;

/**
 * TODO
 *
 * @author xugb
 * @date 2024/4/12 15:15
 */

public abstract class AbstractClientDetailsValidator {
    private static final Logger LOG = LoggerFactory.getLogger(AbstractClientDetailsValidator.class);
    protected OauthTokenService oauthService = SpringFactory.getBean(OauthTokenService.class);
    protected OAuthRequest oauthRequest;
    private AppClientDTO appClientDTO;

    protected AbstractClientDetailsValidator(OAuthRequest oauthRequest) {
        this.oauthRequest = oauthRequest;
    }

    protected AppClientDTO clientDetails() {
        if (this.appClientDTO == null) {
            this.appClientDTO = this.oauthService.getAppClientById(this.oauthRequest.getClientId());
        }

        return this.appClientDTO;
    }

    protected OAuthResponse invalidClientErrorResponse() throws OAuthSystemException {
        return OAuthResponse.errorResponse(401).setError("invalid_client").setErrorDescription("Invalid client_id '" + this.oauthRequest.getClientId() + "'").buildJSONMessage();
    }

    protected OAuthResponse invalidRedirectUriResponse() throws OAuthSystemException {
        return OAuthResponse.errorResponse(400).setError("invalid_request").setErrorDescription("Invalid redirect_uri '" + this.oauthRequest.getRedirectURI() + "'").buildJSONMessage();
    }

    protected OAuthResponse invalidScopeResponse() throws OAuthSystemException {
        return OAuthResponse.errorResponse(400).setError("invalid_scope").setErrorDescription("Invalid scope '" + this.oauthRequest.getScopes() + "'").buildJSONMessage();
    }

    public final OAuthResponse validate() throws OAuthSystemException {
        AppClientDTO details = this.clientDetails();
        return details != null && (0 == details.getArchived()) ? this.validateSelf(details) : this.invalidClientErrorResponse();
    }

    protected boolean excludeScopes(Set<String> scopes, AppClientDTO sysOauthClient) {
        if(StringUtils.isBlank(sysOauthClient.getScope())){
            return false;
        }
        if(scopes.isEmpty()){
            return true;
        }
        String clientDetailsScope = sysOauthClient.getScope();
        for(String scope: scopes){
            if(!clientDetailsScope.contains(scope)){
                LOG.debug("Invalid scope - AppClientDTO scopes '{}' exclude '{}'", clientDetailsScope, scope);
                return true;
            }
        }


        return false;
    }

    protected OAuthResponse invalidClientSecretResponse() throws OAuthSystemException {
        return OAuthResponse.errorResponse(401).setError("unauthorized_client").setErrorDescription("Invalid client_secret by client_id '" + this.oauthRequest.getClientId() + "'").buildJSONMessage();
    }

    protected abstract OAuthResponse validateSelf(AppClientDTO appClientDTO) throws OAuthSystemException;
}
